package com.dbflow5.sql.language;

import com.dbflow5.BaseUnitTest;
import com.dbflow5.models.SimpleModel_Table;
import com.dbflow5.models.SimpleTestModels;
import com.dbflow5.models.TwoColumnModel_Table;
import com.dbflow5.query.NameAlias;
import com.dbflow5.query.Operator;
import com.dbflow5.query.OperatorGroup;
import com.dbflow5.query.SQLite;

import com.dbflow5.query.property.IProperty;
import org.junit.Test;

import java.util.ArrayList;

import static org.junit.Assert.assertEquals;

public class InsertTest extends BaseUnitTest {
    @Test
    public void validateInsert() {
        assertEquals("INSERT INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).values("something").getQuery().trim());
    }

    @Test
    public void validateInsertOr() {
        assertEquals("INSERT OR REPLACE INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orReplace().values("something").getQuery().trim());
        assertEquals("INSERT OR FAIL INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orFail().values("something").getQuery().trim());
        assertEquals("INSERT OR IGNORE INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orIgnore().values("something").getQuery().trim());
        assertEquals("INSERT OR REPLACE INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orReplace().values("something").getQuery().trim());
        assertEquals("INSERT OR ROLLBACK INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orRollback().values("something").getQuery().trim());
        assertEquals("INSERT OR ABORT INTO SimpleModel VALUES('something')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).orAbort().values("something").getQuery().trim());
    }

    @Test
    public void validateQuestionIntention() {
        assertEquals("INSERT INTO SimpleModel VALUES('?')",
            SQLite.insertInto(SimpleTestModels.SimpleModel.class).values("?").getQuery().trim());
    }

    @Test
    public void validateInsertProjection() {
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 'id')",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columns(TwoColumnModel_Table.name, TwoColumnModel_Table.id).values("name", "id").getQuery().trim());
    }

    @Test
    public void validateSelect() {
        assertEquals("INSERT INTO TwoColumnModel SELECT * FROM SimpleModel",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).select(SQLite.select().from(SimpleTestModels.SimpleModel.class)).getQuery().trim());
    }

    @Test
    public void validateColumns() {
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 'id')",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).asColumns().values("name", "id").getQuery().trim());
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 'id')",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columns("name", "id").values("name", "id").getQuery().trim());
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 'id')",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columns(new ArrayList<IProperty<?>>() {
                {
                    add(TwoColumnModel_Table.name);
                    add(TwoColumnModel_Table.id);
                }
            }).values("name", "id").getQuery().trim());

    }

    @Test
    public void validateColumnValues() {
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 0)",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columnValues(SimpleModel_Table.name.eq("name"), TwoColumnModel_Table.id.eq(0)).getQuery().trim());
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 0)",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columnValues(Operator.op(NameAlias.builder("name").build()).eq("name"),
                    TwoColumnModel_Table.id.eq(0)).getQuery().trim());
        assertEquals("INSERT INTO TwoColumnModel(name, id) VALUES('name', 0)",
            SQLite.insertInto(SimpleTestModels.TwoColumnModel.class).columnValues(OperatorGroup.clause().andAll(TwoColumnModel_Table.name.eq("name"), TwoColumnModel_Table.id.eq(0))).getQuery().trim());

    }
}
